/*
 *  settings.cpp
 *  phaseit3d
 *
 *  Created by Anton Barty on 4/9/10.
 *  Copyright 2010 all rights reserved.
 *
 */

#include "settings.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>


/*
 *	Default values
 */
void cSettings::setDefaults(void) {
	
	// Threading defaults
	nthreads = 2;
	niterations = 10000;
	
	
	// File handling
	dvZeroInCorner = 0;
	dvMissingData = -1;
	dvAmplitude = 0;

	supportInCorner = 0;
	guessInCorner = 0;
	

	// Phase retrieval
	prAlgorithm = 1;
	prBeta = 0.9;
	prEpsilon = 0.1;
	prNoisefloor = 0.01;
	prRandomSeed = 1234;
	prErrorReductionFreq = 50;
	
	
	// Shrinkwrap
	sw = 1;
	swStart = 200;
	swStop = 1000;
	swFreq = 100;
	swStartRadius = 3;
	swEndRadius = 0.7;
	swThresh0 = 0.03;
	swThresh = 0.1;
	
	
	// Running sum
	runningSum = 0;
	rsStart = 1500;
	rsFreq = 5;
	
	// FFTW
	fftwSpeedTest=0;
	fftwSanityCheck=0;
	fftwSpeedTestN=256;
	
	
	// Saving
	savefreq = 50;
	
	
	// Default filenames
	strcpy(outdir,".");
	strcpy(diffractionDataFile,"data.h5");
	strcpy(supportDataFile,"support.h5");
	strcpy(guessDataFile,"guess.h5");
	strcpy(logfile,"phaseit3d.log");
	
}




/*
 *	Parse command line arguments 
 */
void cSettings::parseCommandLineArguments(int argc, char **argv) {
	
	// No arguments specified = ask for help
	if (argc == 1) {
		printf("No configuration file spcified\n");
		printf("\t--> using default settings\n");
		return;
	}
	
	// First argument is always the configuration file
	parseConfigFile(argv[1]);
	
	// Other arguments are optional switches but take same syntax prefixed by an '-'
	if (argc > 2) {
		for (long i=2; i<argc; i++) {
			if (argv[i][0] == '-' && i+1 < argc) {
				parseConfigTag(argv[i]+1, argv[++i]);
			}
		}
	}
}



/*
 *	Read and process configuration file
 */
void cSettings::parseConfigFile(char *file) {
	
	char		cbuf[cbufsize];
	char		tag[cbufsize];
	char		value[cbufsize];
	char		*cp;
	FILE		*fp;
	
	
	/*
	 *	Open configuration file for reading
	 */
	printf("Parsing input configuration file: %s\n",file);
	printf("\t%s\n",file);

	fp = fopen(file,"r");
	if (fp == NULL) {
		printf("ERROR: Could not open configuration file \"%s\"\n",file);
		exit(1);
	}
	
	/*
	 *	Loop through configuration file until EOF 
	 *	Ignore lines beginning with a '#' (comments)
	 *	Split each line into tag and value at the '=' sign
	 */
	while (feof(fp) == 0) {
		
		cp = fgets(cbuf, cbufsize, fp);
		if (cp == NULL) 
			break;
		
		if (cbuf[0] == '#')
			continue;
		
		cp = strpbrk(cbuf, "=");
		if (cp == NULL)
			continue;
		
		*(cp) = '\0';
		sscanf(cp+1,"%s",value);
		sscanf(cbuf,"%s",tag);
		
		parseConfigTag(tag, value);
	}
	
	fclose(fp);
	
}


/*
 *	Process tags for both configuration file and command line options
 */
void cSettings::parseConfigTag(char *tag, char *value) {
	
	/*
	 *	Convert to lowercase
	 */
	for(int i=0; i<strlen(tag); i++) 
		tag[i] = tolower(tag[i]);
	
	/*
	 *	Program configuration
	 */
	if (!strcmp(tag, "nthreads")) {
		nthreads = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "niterations")) {
		niterations = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	// Filenames
	else if (!strcmp(tag, "diffractiondata")) {
		strcpy(diffractionDataFile, value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "supportdata")) {
		strcpy(supportDataFile, value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "guessdata")) {
		strcpy(guessDataFile, value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "outdir")) {
		strcpy(outdir, value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	// Data file settings
	else if (!strcmp(tag, "dvzeroincorner")) {
		dvZeroInCorner = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "dvmissingdata")) {
		dvMissingData = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "dvamplitude")) {
		dvAmplitude = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "supportincorner")) {
		supportInCorner = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "guessincorner")) {
		guessInCorner = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	// Phase retrieval
	else if (!strcmp(tag, "pralgorithm")) {
		prAlgorithm = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "prbeta")) {
		prBeta = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "prepsilon")) {
		prEpsilon = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "prnoisefloor")) {
		prNoisefloor = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "prerrorreductionfreq")) {
		prErrorReductionFreq = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	// Shrinkwrap
	else if (!strcmp(tag, "sw")) {
		sw = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swstart")) {
		swStart = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swstop")) {
		swStop = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swfreq")) {
		swFreq = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swstartradius")) {
		swStartRadius = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swendradius")) {
		swEndRadius = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swthresh0")) {
		swThresh0 = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "swthresh")) {
		swThresh = atof(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	// Running sum
	else if (!strcmp(tag, "runningsum")) {
		runningSum = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "rsstart")) {
		rsStart = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "rsfreq")) {
		rsFreq = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}

	// FFTW testing
	else if (!strcmp(tag, "fftwspeedtest")) {
		fftwSpeedTest = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "fftwsanitycheck")) {
		fftwSanityCheck = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	else if (!strcmp(tag, "fftwspeedtestn")) {
		fftwSpeedTestN = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	
	// Saving
	else if (!strcmp(tag, "savefreq")) {
		savefreq = atoi(value);
		printf("\tknown tag : %s = %s\n",tag,value);
	}
	
	else {
		printf("\tUnknown tag (ignored): %s = %s\n",tag,value);
		printf("Quitting \n");
		exit(1);
	}
}


/*
 *	Write log file
 */
void cSettings::writeInitialLogFile(void){
	
	FILE *fp;
		

	// Logfile name
	sprintf(logfile,"%s/phaseit3d.log",outdir);
	printf("Writing log file: %s\n", logfile);
	
	
	
	// Time
	char	timestr[1024];
	time_t	rawtime;
	tm		*timeinfo;
	time(&rawtime);
	timeinfo=localtime(&rawtime);
	strftime(timestr,80,"%c",timeinfo);
	
	
	// Write log file
	fp = fopen (logfile,"w");

	fprintf(fp,"phaseit3d run log\n");
	fprintf(fp,"%s",ctime(&rawtime));
	fprintf(fp,"Nthreads: %i\n",nthreads);
	fprintf(fp,"Niterations: %ld\n",niterations);
	
	fprintf(fp,"Outdir: %s\n",outdir);
	fprintf(fp,"diffractionDataFile: %s\n",diffractionDataFile);
	fprintf(fp,"supportDataFile: %s\n",supportDataFile);
	fprintf(fp,"logfile: %s\n",logfile);
	
	fprintf(fp,"dvZeroInCorner: %i\n",dvZeroInCorner);
	fprintf(fp,"dvMissingData: %f\n",dvMissingData);
	fprintf(fp,"dvAmplitude: %i\n",dvAmplitude);
	fprintf(fp,"supportInCorner: %i\n",supportInCorner);
	
	fprintf(fp,"prAlgorithm: %i\n",prAlgorithm);
	fprintf(fp,"prBeta: %f\n",prBeta);
	fprintf(fp,"prEpsilon: %f\n",prEpsilon);
	fprintf(fp,"prNoisefloor: %f\n",prNoisefloor);
	fprintf(fp,"prErrorReductionFreq: %ld\n",prErrorReductionFreq);
	
	
	fprintf(fp,"sw: %i\n",sw);
	fprintf(fp,"swStart: %li\n",swStart);
	fprintf(fp,"swStop: %li\n",swStop);
	fprintf(fp,"swFreq: %li\n",swFreq);
	fprintf(fp,"swStartRadius: %f\n",swStartRadius);
	fprintf(fp,"swEndRadius: %f\n",swEndRadius);
	fprintf(fp,"swThresh0: %f\n",swThresh0);
	fprintf(fp,"swThresh: %f\n",swThresh);
	
	
	fprintf(fp,"runningSum: %i\n",runningSum);
	fprintf(fp,"rsStart: %li\n",rsStart);
	fprintf(fp,"rsFreq: %li\n",rsFreq);
	
	fprintf(fp,"savefreq: %li\n",savefreq);
	
	fprintf(fp,">-----------------------------------------<\n");
	
	fclose (fp);	
	

}


void cSettings::writeFinalLogFile(void){

}
